/*  

Cafechess Library: Cover basic chess programming needs, like GUI, Engine integration, 
FEN and PGN parsing.

                 \\|//
                 (o o)
--------------ooO-(_)-Ooo----------------------------------
Copyright (C) 2009  By Gregory A. Prentice Snoqualmie, WA
                    www.cafechess.org
                    cafechess@comcast.net
                      Oooo
--------------oooO----(  )---------------------------------
              (  )    (_/
               \_)

Microsoft Public License (Ms-PL)
               
Revisions:

Author        Date    Description:

*/
using System.Text;
using System.Collections;

using Cafechess.Chess.Parsers;
using Cafechess.Chess.General;
namespace Cafechess.Chess.Validation
{
  using Bitboard = System.UInt64;
  using System.Diagnostics;
  using System;
  /// <summary>
  /// Contains the logic to handle bitboard manipulations and move validation.  Initial implementation is discarding
  /// crafties approach of pre-calculated move boards for sliding pieces to get an idea of speed issues that
  /// may be related to CPU cache size and the large amount of data needed to hold all of our tables.
  /// </summary>
  //[CLSCompliant(false)]
  public class StandardValidation: IPositionEvents, IValidation
  {
    #region Constants
    public const string WHITEPIECES = "W";
    public const string BLACKPIECES = "B";
    public const string SQUARE = "S";

    AttackingPieces coAttackingPieces = new AttackingPieces();

    static string [,] coCastleSq = new string[,]
                         {
                           {"f1","g1","h1"},
                           {"d1","c1","a1"},
                           {"f8","g8","h8"},
                           {"d8","c8","a8"},
    };
    #endregion Constants

    #region Attributes
    /// <summary>
    /// algebraic notation.
    /// </summary>
    private ChessMove coMove;
    private Bitboard coMovePieceBoard;
    private int coSquare;
    private string coMovedTo;
    private string coMovedFrom;
    private bool coValidMove;
    private Pieces coPromotionPiece=Pieces.None;
    private bool coSideToMove;

    bool coIsValidating;
    /// <summary>
    /// Holds all of our bitboards for our pieces.
    /// </summary>
    Hashtable coPieceTable;
    // Source squares
    BitboardSquare coFromSquare;
    // Destination squares
    BitboardSquare coToSquare;
    // Our object to create our fen strings
    FenNotation coFenNotation;
    #endregion Attributes;

    #region Properties
    /// <summary>
    /// Not currently implemented
    /// </summary>
    private Bitboard MovePieceBoard
    {
      get{ return coMovePieceBoard; }
      set{ coMovePieceBoard=value;  }
    }
    /// <summary>
    /// Returns the ChessMove object that will contain the
    /// state of the last successfull chess move the validator performed.
    /// If an unsuccessfull move was made then this class will be left in
    /// an unpredictable state.
    /// </summary>
    public ChessMove CurrentMove
    {
      get{ return coMove;}
    }
    /// <summary>
    /// Contains the numeric square value 0 through 63.
    /// <see cref="StandardMoves"/>
    /// </summary>
    public int Square
    {
      get{ return coSquare; }
      set{ coSquare = value; }
    }
    /// <summary>
    /// The algebraic square a piece moved to, does not contain piece.
    /// </summary>
    public string MovedTo
    {
      get{ return coMovedTo; }
      set{ coMovedTo = value;}
    }
    /// <summary>
    /// The algebraic square a piece moved from, does not contain piece.
    /// </summary>
    public string MovedFrom
    {
      get{ return coMovedFrom; }
      set{ coMovedFrom = value;}
    }
    /// <summary>
    /// Will return the standard algebraic chess notation.
    /// </summary>
    public string Notation
    {
      get{ return CurrentMove.ToString();}
    }
    /// <summary>
    /// Will include the standard algebraic chess notation including move number.
    /// </summary>
    public string FullNotation
    {
      get
      {
        StringBuilder build = new StringBuilder();
        int number = CurrentMove.SideToMove ? CurrentMove.FullMove:CurrentMove.FullMove-1;
        build.Append(number.ToString());
        build.Append(CurrentMove.SideToMove ? ".":"..." );
        build.Append(CurrentMove.ToString());
        return  build.ToString();
      }
    }
    /// <summary>
    /// Shows the state of the last move validation, true represents
    /// a successfull move where all Bitboards are updated.
    /// </summary>
    public bool IsValidMove
    {
      get{ return coValidMove; }
      set{ coValidMove = value; }
    }
    /// <summary>
    /// True represents whites turn else it is blacks turn.
    /// </summary>
    public bool SideToMove
    {
      get{ return coSideToMove;}
      set{ coSideToMove = value;}
    }
    #endregion Properties

    #region Constructors
    /// <summary>
    /// Construction of our bitboard to a stable state
    /// </summary>
    public StandardValidation()
    {
      coMove = new ChessMove();
      coFromSquare = new BitboardSquare(0);
      coToSquare = new BitboardSquare(0);
      coPieceTable = new Hashtable();
      coFenNotation=new FenNotation();
      coFenNotation.AddEvents(this);
      AddEvents(coFenNotation);

      coPieceTable[WHITEPIECES] = new ChessPosition(ChessMove.WHITE);
      coPieceTable[BLACKPIECES] = new ChessPosition(ChessMove.BLACK);
      coIsValidating = true;
      SideToMove = ChessMove.WHITE;
    }

    #endregion Constructors

    #region Events
    delegate void Promotion(bool color, string square, ref Pieces piece);
    event Promotion EventPromotion;
    delegate void KingIsMated();
    event KingIsMated EventKingIsMated;
    delegate void KingIsStaleMated();
    event KingIsStaleMated EventKingIsStaleMated;
    delegate void KingIsInCheck();
    event KingIsInCheck EventKingIsInCheck;
    delegate void KingIsFree();
    event KingIsFree EventKingIsFree;
    delegate void BeforeMove(Pieces piece, string from, string to);
    event BeforeMove EventBeforeMove;
    delegate void AfterMove(Pieces piece, string from, string to);
    event AfterMove EventAfterMove;

    delegate void UpdateBoard(Operation op, string FromSquare, string ToSquare,Pieces piece);
    event UpdateBoard EventUpdateBoard;
    delegate void RedrawBoard();
    event RedrawBoard EventRedrawBoard;
//    delegate void FinishedMove();
//    event FinishedMove EventFinishedMove;
    #endregion Events



    #region IParserEventsDelegates

    public delegate void EventPlacePiece(Pieces piece,int square);
    public event EventPlacePiece EventPlacePieceHandler;
    public delegate void EventSideToMove(bool bColor);
    public event EventSideToMove EventSideToMoveHandler;
    public delegate void EventCastling(bool WK, bool WQ, bool BK, bool BQ);
    public event EventCastling EventCastlingHandler;
    public delegate void EventEnpassant( string Enpassant );
    public event EventEnpassant EventEnpassantHandler;
    public delegate void EventHalfMoves(int number);
    public event EventHalfMoves EventHalfMovesHandler;
    public delegate void EventFullMoves(int number);
    public event EventFullMoves EventFullMovesHandler;
    public delegate void EventFinished();
    public event EventFinished EventFinishedHandler;
    public delegate void EventStarting();
    public event EventStarting EventStartingHandler;
    
    #endregion IParserEventsDelegates

    #region Methods
    /// <summary>
    /// Get the specified sides position.
    /// </summary>
    /// <param name="color"></param>
    /// <returns></returns>
    public ChessPosition GetPosition(bool color)
    {
      // Select the correct hash tables based on side to move.
      return (ChessPosition) coPieceTable[color?WHITEPIECES:BLACKPIECES];
    }
    
    /// <summary>
    /// Simply generates the starting positions of all
    /// the pieces.
    /// </summary>
    public void NewBoard()
    {
      ChessPosition Pieces = (ChessPosition) coPieceTable[WHITEPIECES];
      // Init Whites starting position.
      Pieces.NewBoard();
      // Init Black starting position.
      Pieces = (ChessPosition) coPieceTable[BLACKPIECES];
      Pieces.NewBoard();
      //Enpassant = 0;
      CurrentMove.Clear();
    }

    /// <summary>
    /// Clears out all bitboards, setting them to zero.
    /// </summary>
    public void ClearBoard()
    {
      ChessPosition Pieces = (ChessPosition) coPieceTable[WHITEPIECES];
      Pieces.ClearBoard();
      Pieces = (ChessPosition) coPieceTable[BLACKPIECES];
      Pieces.ClearBoard();
      //Enpassant = 0;
      CurrentMove.SideToMove = ChessMove.WHITE;
    }


    public enum Castling { CASTLING_NO, CASTLING_KING, CASTLING_QUEEN, CASTLING_THROUGH_CHECK, CASTLING_ERR }; 

    //If castling, then update related items
    /// <summary>
    /// Determines if castling is legal, then performs 
    /// </summary>
    /// <param name="piece"></param>
    /// <param name="fromSquare"></param>
    /// <param name="Attacker"></param>
    /// <param name="Attacked"></param>
    /// <returns></returns>
    public Castling Castle(Pieces piece, string fromSquare, string toSquare, ChessPosition Attacker, ChessPosition Attacked)
    {
      Bitboard from = BitboardSquare.Mask(fromSquare);
      Bitboard to =   BitboardSquare.Mask(toSquare);
      Pieces rook=Pieces.None;
      Castling Castled = Castling.CASTLING_NO;

      int nIndex = -1;

      if (piece == Pieces.WhiteKing)
      {
        // White may be castling so test.        
        rook=Pieces.WhiteRook;
        if ((to|from &0x0A) == 0x0A) //Castling kingside
        {
          Castled = Castling.CASTLING_KING;
          nIndex = 0;
        }
        else if ((to|from &0x28) == 0x28) //Castling queenside
        {
          Castled = Castling.CASTLING_QUEEN;
          nIndex = 1;
        }
        else
        {
          Attacker.canCastleQueenside = false;
          Attacker.canCastleKingside = false;
        }
      }
      else if (piece == Pieces.BlackKing)
      {
        rook=Pieces.BlackRook;
        if((to|from &0x0A00000000000000) == 0x0A00000000000000 ) //Castling kingside
        {
          Castled = Castling.CASTLING_KING;
          nIndex = 2;
        }
        else if((to|from &0x2800000000000000) == 0x2800000000000000 ) //Castling queenside
        {
          Castled = Castling.CASTLING_QUEEN;
          nIndex = 3;
        }
        else
        {
          Attacker.canCastleQueenside = false;
          Attacker.canCastleKingside = false;
        }
      }
      else if (piece == Pieces.WhiteRook)
      {
        // If rook move then we need to deterimine the side to lose castling 
        if (fromSquare == coCastleSq[1,2])
          Attacker.canCastleQueenside = false;
        else if (fromSquare == coCastleSq[0,2])
          Attacker.canCastleKingside = false;
      }
      else if (piece == Pieces.BlackRook)
      {
        // If rook move then we need to deterimine the side to lose castling 
        if (fromSquare == coCastleSq[3,2])
          Attacker.canCastleQueenside = false;
        else if (fromSquare == coCastleSq[2,2])
          Attacker.canCastleKingside = false;
      }

      if( nIndex != -1 )
      {
        //Save original positions for restoring on errors.
        ChessPosition AttackerS = new ChessPosition(Attacker);
        BitboardSquare fromSq = new BitboardSquare(coFromSquare.Square);
        BitboardSquare toSq   = new BitboardSquare(coToSquare.Square);

        //Is our king in check before castle/can't castle if true?
        if( false == Attacker.IsKingInCheck )
        {
          toSq.AlphaSquare = coCastleSq[nIndex,0];
          Attacker.MovePiece(piece,fromSq, toSq);

          //Is our king in check?
          if( ! StandardMoves.IsKingInCheck(Attacker, Attacked, coAttackingPieces) )
          {
            // Now move the king to 2nd square and test for check.
            fromSq.AlphaSquare = coCastleSq[nIndex,0];
            toSq.AlphaSquare = coCastleSq[nIndex,1];
            Attacker.MovePiece(piece,fromSq,toSq);
            //Is our king is in check?
            if( ! StandardMoves.IsKingInCheck(Attacker, Attacked, coAttackingPieces)  )
            {
              //Now move the rook
              fromSq.AlphaSquare = coCastleSq[nIndex,2];
              toSq.AlphaSquare = coCastleSq[nIndex,0];
              Attacker.MovePiece(rook,fromSq,toSq);
              if( EventUpdateBoard != null )
                EventUpdateBoard(Operation.MOVE, coCastleSq[nIndex,2], coCastleSq[nIndex,0],Pieces.None);
              Attacker.canCastleKingside = false;
              Attacker.canCastleQueenside = false;
            }
            else
              Castled = Castling.CASTLING_THROUGH_CHECK;
          }
          else
            Castled = Castling.CASTLING_THROUGH_CHECK;
        }
        else
          Castled = Castling.CASTLING_ERR;
        
        if( Castled == Castling.CASTLING_THROUGH_CHECK )
        {
          Attacker.Copy(AttackerS);
        }
      }
      return Castled;
    }

    /// <summary>
    /// This routine handles the promotion of a pawn to the requested piece.  It will call the
    /// user routine event associated with EventPromotion() and request that the promotion piece be
    /// selected for the replacement of the pawn.
    /// </summary>
    /// <param name="piece"></param>
    /// <param name="Attacker"></param>
    public void PromotePawn(Pieces piece, ChessPosition Attacker)
    {
      Pieces promotePiece = Pieces.None;
      if( coPromotionPiece != Pieces.None )
      {
      // We are here when coPromotionPiece is not null, we know the movement of a piece was
      //  not initiated by our GUI drag and drop but by a simple call to one of the Move
      //  functions.
        Attacker.RemovePiece(piece,coToSquare.SquareMask());
        PlacePiece(coPromotionPiece, coToSquare.Square); 
        CurrentMove.Promotion = ConvertPiece.ToNotation(coPromotionPiece);
        //coPromotionPiece = Pieces.None;
      }
      else if( (Pieces.WhitePawn == piece && StandardMoves.BitRow(coToSquare.SquareMask()) == 8) ||
        (Pieces.BlackPawn == piece && StandardMoves.BitRow(coToSquare.SquareMask()) == 1) )
      {
        // We are here if the GUI drag and frop opperation moved a pawn to a promotion square.
        if( EventPromotion != null )
        {
          EventPromotion(SideToMove, coToSquare.ToString(), ref promotePiece);
          if(promotePiece != Pieces.None )
          {
            Attacker.RemovePiece(piece,coToSquare.SquareMask());
            PlacePiece(promotePiece,coToSquare.Square); //  BitboardSquare.getSquare(square)
            CurrentMove.Promotion = ConvertPiece.ToNotation(promotePiece);
            if( EventUpdateBoard != null )
              // Changed from coToSquare to coFromSquare as the new drawing logic requires us to
              //  first update where the pawn was before the move.
              EventUpdateBoard(Operation.ADD,coFromSquare.ToString(),null,promotePiece);
          }
        }
      }
    }
    
    /// <summary>
    /// Fires the events to set the values of the currentposition
    /// in a IPositionEvents enabled object such as FenNotation or HuffmanNotation
    /// </summary>
    /// <returns></returns>
    public void Parse()
    {    
      if( EventStartingHandler != null )
        EventStartingHandler();

      Pieces piece = Pieces.None;
      ChessPosition white = GetPosition(true);
      ChessPosition black = GetPosition(false);
      Bitboard mask=BitboardSquare.MaskHighBit;     
      while(mask != 0)
      {        
        if((mask & white.Queens) > 0)
        {
          piece = Pieces.WhiteQueen;
        }
        else if((mask & white.Rooks) > 0)
        {
          piece = Pieces.WhiteRook;
        }
        else if((mask & white.Bishops) > 0)
        {
          piece = Pieces.WhiteBishop;
        }
        else if((mask & white.Knights) > 0)
        {
          piece = Pieces.WhiteKnight;
        }
        else if((mask & white.Pawns) > 0)
        {
          piece = Pieces.WhitePawn;
        }
        else if((mask & white.King) > 0)
        {
          piece = Pieces.WhiteKing;
        }
        else if((mask & black.Queens) > 0)
        {
          piece = Pieces.BlackQueen;
        }
        else if((mask & black.Rooks) > 0)
        {
          piece = Pieces.BlackRook;
        }
        else if((mask & black.Bishops) > 0)
        {
          piece = Pieces.BlackBishop;
        }
        else if((mask & black.Knights) > 0)
        {
          piece = Pieces.BlackKnight;
        }
        else if((mask & black.Pawns) > 0)
        {
          piece = Pieces.BlackPawn;
        }
        else if((mask & black.King) > 0)
        {
          piece = Pieces.BlackKing;
        }
        else
        {
          piece = Pieces.None;
        }
        if( piece != Pieces.None )
        {          
          if(EventPlacePieceHandler!=null)
            EventPlacePieceHandler(piece,BitboardSquare.MaskToSquare(mask));
        }
        mask = mask >> 1;        
      }      
      if(EventSideToMoveHandler != null )
        EventSideToMoveHandler(SideToMove);
      if(EventCastlingHandler != null)
        EventCastlingHandler(white.canCastleKingside,white.canCastleQueenside,black.canCastleKingside,black.canCastleQueenside);
      
      if( white.Enpassant != 0 )
      {
        if(  ((black.Pawns & (white.Enpassant << 1)) > 0 ) ||
          ((black.Pawns & (white.Enpassant >> 1)) > 0 ) )
        {
          if( EventEnpassantHandler != null )
            EventEnpassantHandler(BitboardSquare.MaskToAlpha(white.Enpassant >> 8));
        }
      }
      else if( black.Enpassant != 0 )
      {
        if(  ((white.Pawns & (black.Enpassant << 1)) > 0 ) ||
          ((white.Pawns & (black.Enpassant >> 1)) > 0 ) )
        {
          if( EventEnpassantHandler != null )
            EventEnpassantHandler(BitboardSquare.MaskToAlpha(black.Enpassant << 8));
        }
      }
      
      if( EventHalfMovesHandler != null )
        EventHalfMovesHandler(CurrentMove.HalfMove);

      if( EventFullMovesHandler != null )
        EventFullMovesHandler(CurrentMove.FullMove);

      if( EventFinishedHandler != null )
        EventFinishedHandler();
    }
	
    /// <summary>
    /// Routine used to print any bitboard that we want to.
    /// </summary>
    /// <param name="uboard">bitboard to print</param>
    public void PrintBoard(Bitboard uboard)
    {
      
      Debug.Write(StandardMoves.ToString(uboard));
      Debug.WriteLine("");
    }

    /// <summary>
    /// Simply used for debug purposes, displays the complete
    /// chess bitboard
    /// </summary>
    /// <returns></returns>
    public void PrintBoard()
    {
      Debug.Write(ToString());
      Debug.WriteLine("");
    }

    /// <summary>
    /// Converts the current position into a string representing the bit positions
    /// on the board.
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
      ChessPosition Pieces = (ChessPosition) coPieceTable[WHITEPIECES];
      Bitboard board = Pieces.Board;
      Pieces = (ChessPosition) coPieceTable[BLACKPIECES];
      board = board | Pieces.Board;
      return StandardMoves.ToString(board);
    }
    /// <summary>
    /// This code simply determines if a piece needs its algebraic move qualified
    /// as more than one piece can move to the square.
    /// </summary>
    /// <param name="piece"></param>
    /// <param name="fromSquare"></param>
    /// <param name="Attacker"></param>
    /// <param name="Attacked"></param>
    /// <returns></returns>
    public string Qualified(Pieces piece, string fromSquare, ChessPosition Attacker,ChessPosition Attacked)
    {
      string qualify = "";
      Bitboard piecesAttackingSquare = 0;
      piecesAttackingSquare = StandardMoves.AttackingSquare(piece, coToSquare.SquareMask(), Attacker, Attacked) & ~coFromSquare.SquareMask();
      // Pinned piece but can capture the pinning piece.
      // 8/8/4k3/8/8/8/8/1R1q1RK1 w KQkq
      // Generate any attacking pieces that are pinned.
      // taking in account pieces that can move and
      // capture the pinning piece.
      StandardMoves.Pins(coToSquare.SquareMask(), piecesAttackingSquare,Attacked,Attacker, coAttackingPieces);
      // Get legal piece moves.
      piecesAttackingSquare = piecesAttackingSquare & ~Attacker.Pinned;
      // The value piecesAttackingSquare will be greater than 0 if
      //  two or more pieces could have moved to the same square.
      if( piecesAttackingSquare > 0 )
      {
        Bitboard mask=BitboardSquare.MaskHighBit;
        int samerow=0,samecolm=0;
        // Get the row our piece moved from.
        int row = StandardMoves.BitRow(coFromSquare.SquareMask());
        // Get the column our piece moved from.
        int col = StandardMoves.BitColm(coFromSquare.SquareMask());
        int count=0;
        // Check all of the remaining pieces on the board.
        while(mask != 0)
        {
          if( (mask & piecesAttackingSquare) > 0 )
          {
            // We have a piece so check row/column.
            if( row == StandardMoves.BitRow(mask) )
              samerow++;
            if( col == StandardMoves.BitColm(mask) )
              samecolm++;
            count++;
          }
          mask = mask >> 1;
        }
        if( count > 0 )
        {
          // Only if we have more than one piece that can move there. 
          if( samerow > 0 && samecolm > 0 )
          {
            // Piece is in the same row and column.
            // k7/8/8/8/1N3N2/8/1N3N2/K7 w ----
            // 3 Knights attacking same square.
            // rnbqkbnr/pppp1ppp/8/4p3/2N5/3N1N2/PPPPPPPP/R1BQKB1R w KQkq
            qualify = fromSquare;

            //(count > samerow+samecolm) ) // This line covers knights.
          }
          else if( samerow > 0 )
          {
            // Piece is in the same row  
            // k7/8/8/8/8/8/1N3N2/K7 w ----
            qualify = fromSquare[0].ToString();

          }
          else if( samecolm > 0 )
          {
            // Piece is in the same column.
            // k7/8/8/8/1N6/8/1N36/K7 w ----
            qualify = fromSquare[1].ToString();
          }
          else
          {
            // Piece is not the same row or column.
            //  k7/8/8/8/8/2N5/8/K5N1 w ----
            qualify = fromSquare[0].ToString();
          }
        }
      }
      return qualify;
    }

    /// <summary>
    /// Signals the events for the king's state.
    /// </summary>
    /// <param name="Attacked"></param>
    void FireKingEvents(ChessPosition Attacked)
    {
      if( Attacked.IsKingMated )
      {
        if( EventKingIsMated != null )
          EventKingIsMated();
      }
      else if( Attacked.IsKingInCheck )
      {
        if( EventKingIsInCheck != null )
          EventKingIsInCheck();
      }
      else if( Attacked.IsKingStaleMated )
      {
        if( EventKingIsStaleMated != null )
          EventKingIsStaleMated();
      }
      else
      {
        if( EventKingIsFree != null )
          EventKingIsFree();
      }
    }
    #endregion Methods

    #region IValidation

    public IPositionEvents PositionEvents
    {
      get{ return this;}
    }
    /// <summary>
    /// The FEN notation based on FenFormat.
    /// </summary>
    public string FenNotation 
    {
      get
      {
        Parse();
        return coFenNotation.ToString();
      }
      set
      {
        coFenNotation.Parse(value);
      }
    }
    /// <summary>
    /// Format to use for retrieving the FEN string.
    /// </summary>
    public string FenFormat
    {
      set{ coFenNotation.Format = value; }
    }
    /// <summary>
    /// This routine currently moves a piece by:
    ///  1. Ensures that there is a piece to move
    ///  2. Validates that the piece can move to where it is going.
    ///  3. Updates all associated bitboards when a valid move is made.
    ///  4. Checks for Checks / Mates / Stale Mates.
    /// </summary>
    /// <param name="piece"></param>
    /// <param name="fromSquare"></param>
    /// <param name="toSquare"></param>
    /// <returns></returns>
    public bool Move(Pieces piece, string fromSquare, string toSquare)
    {
      if( EventBeforeMove != null /* && !coEventsInAlgebraic*/) 
        EventBeforeMove(piece,fromSquare,toSquare);

      if( IsValidating )
      {
        IsValidMove = false;
        // Select the correct hash tables based on side to move.
        ChessPosition Attacker = (ChessPosition) coPieceTable[SideToMove?WHITEPIECES:BLACKPIECES];
        ChessPosition Attacked = (ChessPosition) coPieceTable[SideToMove?BLACKPIECES:WHITEPIECES];
        MovedTo = toSquare;
        MovedFrom = fromSquare;


        // Make sure we're not mated already.
        if( ! Attacker.IsKingMated & ! Attacked.IsKingMated )
        {
          coFromSquare.AlphaSquare = fromSquare;
          coToSquare.AlphaSquare = toSquare;

          ChessPosition AttackerS = new ChessPosition(Attacker); //Save original positions for restoring on errors.
          ChessPosition AttackedS = new ChessPosition(Attacked);
        
          // First see if there is a piece to move, and if we are moving in our turn.
          if( (Attacker.Board & coFromSquare.SquareMask()) != (Bitboard)0)
          {
            // Validate if you can move to the destination square.
            //  1. Test to see if we are moving to a square that already
            //  holds one of our own pieces.
            if( (Attacker.Board & coToSquare.SquareMask()) == (Bitboard)0 )
            {
              CurrentMove.ClearMove();
              // Ok we can move there but is it a legal move:
              // Check move available for this piece.            
              Bitboard legalMoves = StandardMoves.LegalMoves(coFromSquare.SquareMask(),piece,Attacker,Attacked);
              if( (legalMoves & coToSquare.SquareMask()) != (Bitboard)0)
              {
                // SAN ****
                // k7/8/8/8/8/8/2N3N1/K7 w ----
                // Start building your SAN notation.
                CurrentMove.Piece = ConvertPiece.ToNotation(piece);
                CurrentMove.Move = toSquare;
                CurrentMove.SideToMove = SideToMove;
                // Returns a qualifying square/row if needed for piece resolution.
                CurrentMove.Qualify = Qualified(piece,fromSquare,Attacker,Attacked);
                // **** SAN
                // See if there has been a piece capture.
                if( (Attacked.Board & coToSquare.SquareMask()) != (Bitboard)0 )
                {
                  // SAN ****
                  CurrentMove.Capture = true;
                  if( CurrentMove.Piece == 'P' )
                    CurrentMove.Qualify = fromSquare[0].ToString();
                  // **** SAN
                  // Determine which piece we just captured and remove it.
                  CurrentMove.Captured = Attacked.RemovePiece(coToSquare);
                }
                else if( Attacker.CaptureEnpassant == coToSquare.SquareMask() )
                {
                  if( piece == Pieces.WhitePawn || piece == Pieces.BlackPawn )
                  {
                    int square = ((StandardMoves.BitColm(Attacked.Enpassant)-1) + ((StandardMoves.BitRow(Attacked.Enpassant)- 1) * 8));
                    Attacked.RemovePiece(Pieces.WhitePawn, new BitboardSquare(square) );
                    if(EventUpdateBoard != null )
                      EventUpdateBoard(Operation.Delete, BitboardSquare.SquareToAlpha(square), null, Pieces.None);
                    CurrentMove.Qualify = fromSquare[0].ToString();
                    CurrentMove.Capture = true;
                  }
                }
                // Clear as we are done with this value.
                Attacker.CaptureEnpassant = 0;
                //Are we castling? The castle function moves the pieces and tests for incheck.
                Castling isCastled = Castle(piece, fromSquare, toSquare, Attacker, Attacked);
                switch(isCastled)
                {
                  case Castling.CASTLING_NO:
                    // Not castling so now just make our normal moves and
                    // test for 
                    Attacker.MovePiece(piece, coFromSquare, coToSquare);
                    //Is side to move's king in check?
                    if (StandardMoves.IsKingInCheck(Attacker, Attacked, coAttackingPieces) )
                    {
                      Attacker.Copy(AttackerS);
                      Attacked.Copy(AttackedS);
                    }
                    else
                    {
                      // Check to see if we want to promote a pawn.
                      PromotePawn(piece, Attacker);
                      IsValidMove = true;
                    }
                    StandardMoves.IsKingCheckedMatedStaled(Attacker,Attacked, coAttackingPieces);
                    break;
                  case Castling.CASTLING_KING:
                  case Castling.CASTLING_QUEEN:
                    if( isCastled == Castling.CASTLING_KING) 
                      CurrentMove.CastleKingside = true;
                    else if( isCastled == Castling.CASTLING_QUEEN)
                      CurrentMove.CastleQueenside = true;
                    // Check to see if we have attacked the opponents king.
                    StandardMoves.IsKingCheckedMatedStaled(Attacker,Attacked, coAttackingPieces);
                    IsValidMove = true;
                    break;
                }
                if(Attacked.IsKingMated)
                  CurrentMove.Mate = Attacked.IsKingMated;
                else if( Attacked.IsKingInCheck )
                  CurrentMove.Check = Attacked.IsKingInCheck;
                // Fire events to anyone who wants to know regarding our Attacked kings status.
                FireKingEvents(Attacked);

                if( IsValidMove )
                {
                  Attacked.Enpassant = 0;
                  if(SideToMove == false )
                  {
                    // Black moved successfully so let inc our move number.
                    CurrentMove.FullMove++;
                  }
                  if(CurrentMove.Capture || CurrentMove.Piece == 'P')
                  {
                    CurrentMove.HalfMove = 0;
                  }
                  else
                  {
                    // Keep track of our 50 move draw rule.
                    CurrentMove.HalfMove++;
                  }
                  // We need to see if a rook was capture as the disallows castling on that
                  //  side of the board.
                  if(CurrentMove.Capture && (CurrentMove.Captured == Pieces.WhiteRook ||
                    CurrentMove.Captured == Pieces.BlackRook    ))
                  {
                    Bitboard to = coToSquare.SquareMask();
                    Bitboard kingMask = SideToMove ?  (ulong)0x0100000000000000 : (ulong)0x01;
                    Bitboard queenMask = SideToMove ? (ulong)BitboardSquare.MaskHighBit : (ulong)0x80;
                    if(Attacked.canCastleKingside)
                    {
                      Attacked.canCastleKingside = ((to&kingMask) == 0);
                    }
                    if(Attacked.canCastleQueenside)
                    {
                      Attacked.canCastleQueenside = ((to&queenMask) == 0);
                    }
                  }
                  // Switch color to move.
                  SideToMove = !SideToMove;
                  // Do we need to update the GUI by moving pieces?
                  if( EventUpdateBoard != null )
                  {
                    if(coPromotionPiece == Pieces.None )
                      EventUpdateBoard(Operation.MOVE,  fromSquare,toSquare,Pieces.None);
                    else
                    {
                      EventUpdateBoard(Operation.Delete,fromSquare,null,Pieces.None);
                      EventUpdateBoard(Operation.ADD,toSquare,null,coPromotionPiece);
                      coPromotionPiece = Pieces.None;
                    }
                  }
                }
              }
            }
          }
        }
        else
        {
          IsValidMove = true;
        }
      }
      else
      {
        // All moves are valid.
        IsValidMove = true;
        if( EventUpdateBoard != null )
        {
          EventUpdateBoard(Operation.MOVE,  fromSquare,toSquare,Pieces.None);
        }
      }
      // Force the GUI to redraw itself.
      if( EventRedrawBoard != null )
        EventRedrawBoard();

      if( EventAfterMove != null /* && !coEventsInAlgebraic */)
        EventAfterMove(piece,fromSquare,toSquare);

      return IsValidMove;
    }
  
    /// <summary>
    /// Parses out our Algebraic notation and then makes the move.
    /// This is a slower process then calling the function
    /// move("e2","e4") which does not have to compute the source
    /// piece that is actually moving.
    /// </summary>
    /// <param name="move"></param>
    /// <returns></returns>
    public bool Move(string algebraic)
    {  
      bool bOK=false;
      if( IsValidating )
      {
        string moveToSquare=null, moveFromSquare=null;      
        Pieces aPiece;//5 = Color ? Pieces.WhitePawn : Pieces.BlackPawn ;
        CurrentMove.Parse(algebraic);

        if( CurrentMove.Promotion != ' ' )
        {
          coPromotionPiece = ConvertPiece.FromFEN( SideToMove ? CurrentMove.Promotion.ToString().ToUpper()[0]:
            CurrentMove.Promotion.ToString().ToLower()[0]);
        }
        else
          coPromotionPiece = Pieces.None;


        // Convert to public piece representation.
        aPiece = ConvertPiece.FromFEN( SideToMove ? CurrentMove.Piece.ToString().ToUpper()[0]:
          CurrentMove.Piece.ToString().ToLower()[0]);
        // Select the correct hash tables based on side to move.
        ChessPosition Attacker = (ChessPosition) coPieceTable[SideToMove?WHITEPIECES:BLACKPIECES];
        ChessPosition Attacked = (ChessPosition) coPieceTable[SideToMove?BLACKPIECES:WHITEPIECES];     
        if(CurrentMove.CastleKingside)
        {
          moveToSquare = SideToMove?"g1":"g8";
          moveFromSquare = SideToMove?"e1":"e8";
          aPiece = SideToMove?Pieces.WhiteKing:Pieces.BlackKing;
        }
        else if(CurrentMove.CastleQueenside)
        {
          moveToSquare = SideToMove?"c1":"c8";
          moveFromSquare = SideToMove?"e1":"e8";
          aPiece = SideToMove?Pieces.WhiteKing:Pieces.BlackKing;
        }
        else
        {
          Bitboard moves=0, moveTo=0,moveFrom=0;
          moveToSquare = CurrentMove.Move;
          moveTo = BitboardSquare.Mask(CurrentMove.Move);
          if(aPiece == Pieces.BlackPawn )
          {
            if(CurrentMove.Capture)
            {
              if(CurrentMove.Qualify.Length == 1)
              {
                if(CurrentMove.Qualify[0] > CurrentMove.Move[0])
                  moveFrom = (moveTo << 7) & Attacker.Pawns;
                else
                  moveFrom = (moveTo << 9) & Attacker.Pawns;
              }
              else
              {
                // Just in case the move was not qualified we need
                // to protect against more than one capture.
                moveFrom = (moveTo << 7) & Attacker.Pawns;
                if(moveFrom == 0 )
                  moveFrom = (moveTo << 9) & Attacker.Pawns;
              }
            }
            else
            {
              // See if a pawn can move one square forward.
              moveFrom = moveTo << 8 & Attacker.Pawns;
              if( moveFrom == 0 )
              {
                moveTo <<= 16;
                // Only pawns on seventh row
                if((BitboardSquare.RowOrColm('7') & moveTo) > 0)
                {
                  // Check to see if we have a pawn that can move two squares and 
                  //  there was no pawn in front of it.
                  moveFrom = moveTo & Attacker.Pawns;           
                }
              }
            }
            if( moveFrom > 0 )
              moveFromSquare = BitboardSquare.SquareToAlpha(BitboardSquare.MaskToSquare(moveFrom));
          }
          else if( aPiece == Pieces.WhitePawn )
          {
            if(CurrentMove.Capture)
            {
              if(CurrentMove.Qualify.Length == 1)
              {
                if(CurrentMove.Qualify[0] > CurrentMove.Move[0])
                  moveFrom = (moveTo >> 9) & Attacker.Pawns;
                else
                  moveFrom = (moveTo >> 7) & Attacker.Pawns;              
              }
              else
              {
                // Just in case the move was not qualified we need
                // to protect against more than one capture.
                moveFrom = (moveTo >> 7) & Attacker.Pawns;
                if(moveFrom == 0 )
                  moveFrom = (moveTo >> 9) & Attacker.Pawns;
              }            
            }
            else
            {
              // moves = moveTo >> 8 | moveTo >> 16;
              // See if a pawn can move one square forward.
              moveFrom = (moveTo >> 8) & Attacker.Pawns;
              if( moveFrom == 0 )
              {
                moveTo >>= 16;
                // Only pawns on second row
                if((BitboardSquare.RowOrColm('2') & moveTo) > 0)
                  // Check to see if we have a pawn that can move two squares and 
                  //  there was no pawn in front of it.
                  moveFrom = moveTo & Attacker.Pawns;
              }
            }
            if( moveFrom > 0 )
              moveFromSquare = BitboardSquare.SquareToAlpha(BitboardSquare.MaskToSquare(moveFrom));
          }
          else
          {
            if(CurrentMove.Qualify.Length == 2)
            {
              moveFromSquare = CurrentMove.Qualify;
            }
            else
            {
              // Get the moves as if our destination square is where our piece is currently located.
              //  We'll later use this to determine what piece we are moving.
              moves = StandardMoves.LegalMoves( moveTo, aPiece, Attacker, Attacked);
              // Get our piece or pieces that we may be moving.
              moveFrom = moves & Attacker.GetPiece(aPiece);
              // Generate pinned pieces as we can only move that piece on 
              //  the same line as the pin or capture the pinning piece if possible.
              StandardMoves.Pins(Attacked, Attacker, coAttackingPieces);
              // Nights can't move if they are pinned period!!
              if( aPiece == Pieces.WhiteKnight ||
                aPiece == Pieces.BlackKnight )
              {
                moveFrom = ~Attacker.Pinned & moveFrom;
              }
              else if( (Attacker.Pinned & moveFrom) > 0 )
              {
                // One of our pieces is pinned, a pinned piece may move 
                //  anywhere along the line of attack, including capture of
                //  the pinning piece.
                // Make sure we only pass one bit per argument:
                //  below should resolved to the pinned piece.
                Bitboard pinned  = (Attacker.Pinned & moveFrom);
                // Make sure we only pass one bit per argument:
                //  below should resolved to the pinning piece.             
                Bitboard pinning = StandardMoves.PinningPiece(pinned,Attacked,Attacker, coAttackingPieces);
                // Pinning piece can not be captured such as a bishop pinning a rook.
                if( pinning != 0 )
                {
                  // Get all direct attack between pinning/pinned/king.
                  Bitboard direct  = StandardMoves.DirectAttack(pinned,pinning) | StandardMoves.DirectAttack(pinned,Attacker.King);
                  // A piece is able to move if it is along the proper line of attack.
                  if( (moveTo & direct) == 0 )
                    // Can't move along line or capture pinning piece.
                    moveFrom = moveFrom & (~Attacker.Pinned);
                }
                else
                {
                  // Pinned piece can't move along line or capture pinning piece.
                  //  Such as a bishop pinning a rook....
                  moveFrom = moveFrom & (~Attacker.Pinned);
                }

              }
              // See if we found the piece.
              if( moveFrom > 0 )
              {
                // Do we need to get the specific row or column?
                if( CurrentMove.Qualify.Length == 1)
                {
                  moveFrom = moveFrom & BitboardSquare.RowOrColm(CurrentMove.Qualify[0]);
                }
                // We can only get a source square if our bit is one....
                if( StandardMoves.CountBits(moveFrom) == 1 )
                  moveFromSquare = BitboardSquare.SquareToAlpha(BitboardSquare.MaskToSquare(moveFrom));              
              }
            }
          }
        }
        if( moveFromSquare != null && moveToSquare != null )
        {

          bOK = Move(aPiece,moveFromSquare,moveToSquare);
        }
      }
      else
      {
        bOK = true;
        IsValidMove = true;
      }
      return bOK;
    }

    public bool IsValidating
    { 
      get{ return coIsValidating;} 
      set{ coIsValidating = value;}
    }    
    /// Retrieves a bit array of all squares a color is attacing.
    /// </summary>
    /// <param name="color"></param>
    /// <returns></returns>
    public BitArray Attacks(bool color)
    {
      // Select the correct hash tables based on side to move.
      ChessPosition Attacker = (ChessPosition) coPieceTable[color?WHITEPIECES:BLACKPIECES];
      ChessPosition Attacked = (ChessPosition) coPieceTable[color?BLACKPIECES:WHITEPIECES];
      Bitboard pawnMoves=0;
      Bitboard board = StandardMoves.Attacks(Attacker,Attacked, StandardMoves.Suppress.GETALL,out pawnMoves);
      BitArray bits = new BitArray(64);
      SetBitArray(bits,board);
      return bits;
    }
    /// <summary>
    /// Retrieves a bit array of the squares a piece would attack.
    /// </summary>
    /// <param name="piece"></param>
    /// <param name="square"></param>
    /// <returns></returns>
    public BitArray Moves(Pieces piece, int square)
    {
      Bitboard board = StandardMoves.PieceMoves(piece,BitboardSquare.Mask(square));
      BitArray bits = new BitArray(64);
      SetBitArray(bits,board);     
      return bits;
    }
    /// <summary>
    /// A simple helper function that will set the bits in a BitArray class
    /// to the values in our Bitboard parameter.
    /// </summary>
    /// <param name="bits"></param>
    /// <param name="board"></param>
    public void SetBitArray(BitArray bits, Bitboard board)
    { 
      Bitboard mask = BitboardSquare.MaskHighBit;
      while(mask > 0)
      {               
        bits.Set(BitboardSquare.MaskToSquare(mask), (board & mask) > 0 ? true : false);
        mask = mask >> 1;
      }
    }
    
    //  Need to look at moving this to an evaluation interface or function.
    public int[] WeightWeakSquares()
    {
      //Bitboard board = 0;
      Bitboard work = 0;
      int[] weakSquares = new int[64];
      int index;
      int owner = 0;
      Bitboard mask = BitboardSquare.MaskHighBit;
      // Select the correct hash tables based on side to move.
      ChessPosition white = (ChessPosition)coPieceTable[WHITEPIECES];
      ChessPosition black = (ChessPosition)coPieceTable[BLACKPIECES];
      while (mask != 0)
      {
        work = StandardMoves.AttackingSquare(mask, white, black);
        owner = StandardMoves.CountBits(work);
        work = StandardMoves.AttackingSquare(mask, black, white);
        owner = owner - StandardMoves.CountBits(work);
        index = BitboardSquare.MaskToSquare(mask);
        weakSquares[index] = owner;
        mask = mask >> 1;
      }
      return weakSquares;
    }

    /// <summary>
    /// Allows other objects to register themselves as interested in any
    /// events the validation routine fires.
    /// </summary>
    /// <param name="ievents"></param>
    public void AddEvents(IValidationEvents ievents)
    {
      EventPromotion += new Promotion(ievents.Promotion);
      EventKingIsMated += new KingIsMated(ievents.KingIsMated);
      EventKingIsStaleMated += new KingIsStaleMated(ievents.KingIsStaleMated);
      EventKingIsInCheck += new KingIsInCheck(ievents.KingIsInCheck);
      EventKingIsFree += new KingIsFree(ievents.KingIsFree);
      EventBeforeMove += new BeforeMove(ievents.BeforeMove);
      EventAfterMove += new AfterMove(ievents.AfterMove);
    }

    /// <summary>
    /// Allows other objects to un-register themselves as no longer interested 
    /// in events the validation routine fires.
    /// </summary>
    /// <param name="ievents"></param>
    public void RemoveEvents(IValidationEvents ievents)
    {
      EventPromotion -= new Promotion(ievents.Promotion);
      EventKingIsMated -= new KingIsMated(ievents.KingIsMated);
      EventKingIsStaleMated -= new KingIsStaleMated(ievents.KingIsStaleMated);
      EventKingIsInCheck -= new KingIsInCheck(ievents.KingIsInCheck);
      EventKingIsFree -= new KingIsFree(ievents.KingIsFree);
      EventBeforeMove -= new BeforeMove(ievents.BeforeMove);
      EventAfterMove -= new AfterMove(ievents.AfterMove);
    }

    /// <summary>
    /// Allows other objects to register themselves as interested in any
    /// UI events the validation routine fires.
    /// </summary>
    /// <param name="ievents"></param>
    public void AddEvents(IValidationUIEvents ievents)
    {
      EventUpdateBoard += new UpdateBoard(ievents.UpdateBoard);
      EventRedrawBoard += new RedrawBoard(ievents.RedrawBoard);
    }
    /// <summary>
    /// Allows other objects to un-register themselves as no longer interested 
    /// in UI events the validation routine fires.
    /// </summary>
    /// <param name="ievents"></param>
    public void RemoveEvents(IValidationUIEvents ievents)
    {
      EventUpdateBoard -= new UpdateBoard(ievents.UpdateBoard);
      EventRedrawBoard -= new RedrawBoard(ievents.RedrawBoard);    
    }
    #endregion IValidation

    #region IPositionEvents
    /// <summary>
    /// Adds the requested piece to our bitboards.
    /// </summary>
    /// <param name="piece"></param>
    /// <param name="square"></param>
    public void PlacePiece(Pieces piece, int square)
    {
      // Select the correct hash tables based on side to move.
      ChessPosition position = (ChessPosition) coPieceTable[piece < Pieces.BlackKing?WHITEPIECES:BLACKPIECES];
      //coToSquare = getBitSquare(square);
      position.AddPiece(piece, new BitboardSquare(square));
    }

    /// <summary>
    /// Will set the current castling privilages of the validator.
    /// </summary>
    /// <param name="WK"></param>
    /// <param name="WQ"></param>
    /// <param name="BK"></param>
    /// <param name="BQ"></param>
    public void SetCastling(bool WK, bool WQ, bool BK, bool BQ)
    {
      ChessPosition WhiteSide = (ChessPosition) coPieceTable[WHITEPIECES];
      ChessPosition BlackSide = (ChessPosition) coPieceTable[BLACKPIECES];
      WhiteSide.canCastleKingside = WK;
      WhiteSide.canCastleQueenside = WQ;
      BlackSide.canCastleKingside = BK;
      BlackSide.canCastleQueenside = BQ;
    }
    /// <summary>
    /// Sets the validators enpasant capture square.
    /// </summary>
    /// <param name="Enpassant"></param>
    public void SetEnpassant( string Enpassant )
    {
      ChessPosition Attacker = (ChessPosition) coPieceTable[SideToMove?BLACKPIECES:WHITEPIECES];
      Attacker.Enpassant = BitboardSquare.Mask(Enpassant);
      if( !SideToMove )
        Attacker.Enpassant = ( Attacker.Enpassant << 8 ) & Attacker.Pawns;
      else
        Attacker.Enpassant = ( Attacker.Enpassant >> 8 ) & Attacker.Pawns;
    }
    /// <summary>
    /// Sets how many moves have been made since the last pawn move or capture.
    /// </summary>
    /// <param name="number"></param>
    public void SetHalfMoves(int number)
    {
      CurrentMove.HalfMove = number;
    }

    /// <summary>
    /// Sets how many moves have been made in the game so far.
    /// </summary>
    /// <param name="number"></param>
    public void SetFullMoves(int number)
    {
      CurrentMove.FullMove = number;

    }
    /// <summary>
    /// Sets the side to move property.
    /// </summary>
    /// <param name="bColor"></param>
    public void SetSideToMove(bool bColor)
    {
      SideToMove = bColor;
    }
    /// <summary>
    /// We've finished receiving events for the position setup so lets
    /// </summary>
    public void Finished()
    {
      // Select the correct hash tables based on side to move.
      ChessPosition Attacker = (ChessPosition) coPieceTable[SideToMove?WHITEPIECES:BLACKPIECES];
      ChessPosition Attacked = (ChessPosition) coPieceTable[SideToMove?BLACKPIECES:WHITEPIECES];
      StandardMoves.IsKingCheckedMatedStaled(Attacked , Attacker, coAttackingPieces);
    }
    /// <summary>
    /// Starting to receive events so lets reset the validator.
    /// </summary>
    public void Starting()
    {
      ClearBoard();
    }
    #endregion

    public void AddEvents(IPositionEvents ievents)
    {
      EventPlacePieceHandler += new EventPlacePiece(ievents.PlacePiece);
      EventSideToMoveHandler += new EventSideToMove(ievents.SetSideToMove);
      EventCastlingHandler += new EventCastling(ievents.SetCastling);
      EventEnpassantHandler += new EventEnpassant(ievents.SetEnpassant);
      EventHalfMovesHandler += new EventHalfMoves(ievents.SetHalfMoves);
      EventFullMovesHandler += new EventFullMoves(ievents.SetFullMoves);
      EventFinishedHandler += new EventFinished(ievents.Finished);
      EventStartingHandler += new EventStarting(ievents.Starting);
    }
    public void RemoveEvents(IPositionEvents ievents)
    {
      EventPlacePieceHandler -= new EventPlacePiece(ievents.PlacePiece);
      EventSideToMoveHandler -= new EventSideToMove(ievents.SetSideToMove);
      EventCastlingHandler -= new EventCastling(ievents.SetCastling);
      EventEnpassantHandler -= new EventEnpassant(ievents.SetEnpassant);
      EventHalfMovesHandler -= new EventHalfMoves(ievents.SetHalfMoves);
      EventFullMovesHandler -= new EventFullMoves(ievents.SetFullMoves);
      EventFinishedHandler -= new EventFinished(ievents.Finished);
      EventStartingHandler -= new EventStarting(ievents.Starting);
    }
  }
}
